


#undef CB_PRECOMP
#ifndef CB_PRECOMP
    #include <wx/dir.h>
    #include <wx/file.h>
    #include <wx/imaglist.h>
    #include <wx/listctrl.h>
    #include <wx/menu.h>
    #include <wx/notebook.h>
    #include <wx/regex.h>
    #include <wx/splitter.h>

    #include "seditormanager.h"
    #include "configmanager.h"
    #include "infowindow.h"
    #include "logmanager.h"
    #include "projectmanager.h"
    #include "projectfile.h"
    #include "pluginmanager.h"
    #include "manager.h"
    #include "filemanager.h"
    #include "sdk_events.h"
    #include "projectbuildtarget.h"
    #include "cbproject.h"
    #include "scbeditor.h"
    #include "globals.h"
    #include "sdk_events.h"
#endif
#include "cbstyledtextctrl.h"

#include <wx/bmpbuttn.h>
#include <wx/progdlg.h>
#include <wx/fontutil.h>
#include <wx/tokenzr.h>
#include "seditorcolourset.h"
#include "encodingdetector.h"
#include "findreplacedlg.h"
#include "confirmreplacedlg.h"
#include "filefilters.h"
#include "searchresultslog.h"
#include "projectfileoptionsdlg.h"
#include "filegroupsandmasks.h"

#include "cbauibook.h"
#include "snippetsconfig.h"
#include "seditormanager.h"
#include "scbeditor.h"
#include "sprintdlg.h"
#include "editproperties.h"
#if defined(LOGGING)
    #include "version.h"
#endif



int ID_NBSEditorManager = wxNewId();
int ID_SEditorManager = wxNewId();
int idSEditorManagerCheckFiles = wxNewId();

// static
bool SEditorManager::s_CanShutdown = true;

struct cbFindReplaceData
{
    int start;
    int end;
    wxString findText;
    wxString replaceText;
    bool initialreplacing;
    bool findInFiles;
    bool delOldSearches;
    bool matchWord;
    bool startWord;
    bool matchCase;
    bool regEx;
    bool directionDown;
    bool originEntireScope;
    int scope;
    wxString searchPath;
    wxString searchMask;
    bool recursiveSearch;
    bool hiddenSearch;
    bool NewSearch;    
    int SearchInSelectionStart;
    int SearchInSelectionEnd; 
    bool autoWrapSearch;
    bool findUsesSelectedText;
};

static const int idNBTabSplitHorz = wxNewId();
static const int idNBTabSplitVert = wxNewId();
static const int idNBTabUnsplit = wxNewId();
static const int idNBTabClose = wxNewId();
static const int idNBTabCloseAll = wxNewId();
static const int idNBTabCloseAllOthers = wxNewId();
static const int idNBTabSave = wxNewId();
static const int idNBTabSaveAll = wxNewId();
static const int idNBSwapHeaderSource = wxNewId();
static const int idNBTabTop = wxNewId();
static const int idNBTabBottom = wxNewId();
static const int idNBProperties = wxNewId();
static const int idNB = wxNewId();



struct EditorManagerInternalData
{
    

    EditorManagerInternalData(SEditorManager* owner)
            : m_pOwner(owner)
    {}

    

    SEditorManager* m_pOwner;
    bool m_SetFocusFlag;
};



BEGIN_EVENT_TABLE(SEditorManager, wxEvtHandler)
    EVT_APP_STARTUP_DONE(SEditorManager::OnAppDoneStartup)
    EVT_APP_START_SHUTDOWN(SEditorManager::OnAppStartShutdown)
    EVT_AUINOTEBOOK_PAGE_CHANGED(ID_NBSEditorManager, SEditorManager::OnPageChanged)
    EVT_AUINOTEBOOK_PAGE_CHANGING(ID_NBSEditorManager, SEditorManager::OnPageChanging)
    EVT_AUINOTEBOOK_PAGE_CLOSE(ID_NBSEditorManager, SEditorManager::OnPageClose)
    EVT_AUINOTEBOOK_TAB_RIGHT_UP(ID_NBSEditorManager, SEditorManager::OnTabRightUp)
    EVT_MENU(idNBTabSplitHorz, SEditorManager::OnGenericContextMenuHandler)
    EVT_MENU(idNBTabSplitVert, SEditorManager::OnGenericContextMenuHandler)
    EVT_MENU(idNBTabUnsplit, SEditorManager::OnGenericContextMenuHandler)
    EVT_MENU(idNBTabTop, SEditorManager::OnTabPosition)
    EVT_MENU(idNBTabBottom, SEditorManager::OnTabPosition)
    EVT_MENU(idNBTabClose, SEditorManager::OnClose)
    EVT_MENU(idNBTabCloseAll, SEditorManager::OnCloseAll)
    EVT_MENU(idNBTabCloseAllOthers, SEditorManager::OnCloseAllOthers)
    EVT_MENU(idNBTabSave, SEditorManager::OnSave)
    EVT_MENU(idNBTabSaveAll, SEditorManager::OnSaveAll)
    EVT_MENU(idNBSwapHeaderSource, SEditorManager::OnSwapHeaderSource)
    EVT_MENU(idNBProperties, SEditorManager::OnProperties)
    EVT_MENU(idSEditorManagerCheckFiles, SEditorManager::OnCheckForModifiedFiles)
END_EVENT_TABLE()


SEditorManager::SEditorManager(wxWindow* parent)
// ----------------------------------------------------------------------------
        : m_pNotebook(0L),
        m_LastFindReplaceData(0L),
        m_pSearchLog(0),
        m_SearchLogIndex(-1),
        m_SashPosition(150),
        m_isCheckingForExternallyModifiedFiles(false) {
    InitSEditorManager(parent);
}

void SEditorManager::InitSEditorManager(wxWindow* parent) {
    m_pParent = parent;
    GetConfig()->RegisterEditorManager( (wxFrame*)parent, this );
    m_pData = new EditorManagerInternalData(this);

    m_pNotebook = new cbAuiNotebook( parent, ID_NBSEditorManager, wxDefaultPosition, wxDefaultSize, wxNO_FULL_REPAINT_ON_RESIZE | wxCLIP_CHILDREN);
    m_pNotebook->SetWindowStyleFlag(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/environment/editor_tabs_style"), wxAUI_NB_DEFAULT_STYLE | wxAUI_NB_MIDDLE_CLICK_CLOSE));

    Manager::Get()->GetLogManager()->DebugLog(_T("Initialize EditColourSet ....."));

    m_Theme = 0;
   
    m_Theme = new SEditorColourSet(Manager::Get()->GetConfigManager(_T("editor"))->Read(_T("/colour_sets/active_colour_set"), COLORSET_DEFAULT));
    Manager::Get()->GetLogManager()->DebugLog(_T("Initialize EditColourSet: done."));

   
    parent->PushEventHandler(this);

   
   

    LoadAutoComplete();
    m_zoom = Manager::Get()->GetConfigManager(_T("editor"))->ReadInt(_T("/zoom"));
}


SEditorManager::~SEditorManager() {
    SaveAutoComplete();


    if (m_pSearchLog)
    {
        CodeBlocksLogEvent evt(cbEVT_REMOVE_LOG_WINDOW, m_pSearchLog);
        Manager::Get()->ProcessEvent(evt);
        m_pSearchLog = 0;
    }

    delete m_Theme;
    delete m_LastFindReplaceData;
    delete m_pData;
    Manager::Get()->GetConfigManager(_T("editor"))->Write(_T("/zoom"), m_zoom);

   
    m_pParent->RemoveEventHandler(this);
   
    GetConfig()->RemoveEditorManager((wxFrame*)m_pParent );

}

void SEditorManager::CreateMenu(wxMenuBar* menuBar) {
}

void SEditorManager::ReleaseMenu(wxMenuBar* menuBar) {
}

void SEditorManager::CreateSearchLog() {
    if (Manager::IsBatchBuild())
        return;

    wxArrayInt widths;
    wxArrayString titles;
    titles.Add(_("File"));
    titles.Add(_("Line"));
    titles.Add(_("Text"));
    widths.Add(128);
    widths.Add(48);
    widths.Add(640);

    wxString prefix = ConfigManager::GetDataFolder() + _T("/images/16x16/");
    wxBitmap * bmp = new wxBitmap(cbLoadBitmap(prefix + _T("filefind.png"), wxBITMAP_TYPE_PNG));

    m_pSearchLog = new cbSearchResultsLog(titles, widths);
    CodeBlocksLogEvent evt(cbEVT_ADD_LOG_WINDOW, m_pSearchLog, _("Search results"), bmp);
    Manager::Get()->ProcessEvent(evt);
}

void SEditorManager::LogSearch(const wxString& file, int line, const wxString& lineText) {
    wxArrayString values;
    wxString lineTextL;
    wxString lineStr;

   
    if( line != -1)
    {
        lineStr.Printf(_T("%d"), line);
    }
    else
    {
        lineStr.Printf(_T(" "));
    }
    lineTextL = lineText;
    lineTextL.Replace(_T("\t"), _T(" "));
    lineTextL.Replace(_T("\r"), _T(" "));
    lineTextL.Replace(_T("\n"), _T(" "));
    lineTextL.Trim(false);
    lineTextL.Trim(true);

    values.Add(file);
    values.Add(lineStr);
    values.Add(lineTextL);

    m_pSearchLog->Append(values, line == -1 ? Logger::caption : Logger::info);
}

void SEditorManager::LoadAutoComplete() {
    m_AutoCompleteMap.clear();
    wxArrayString list = Manager::Get()->GetConfigManager(_T("editor"))->EnumerateSubPaths(_T("/auto_complete"));
    for (unsigned int i = 0; i < list.GetCount(); ++i)
    {
        wxString name = Manager::Get()->GetConfigManager(_T("editor"))->Read(_T("/auto_complete/") + list[i] + _T("/name"), wxEmptyString);
        wxString code = Manager::Get()->GetConfigManager(_T("editor"))->Read(_T("/auto_complete/") + list[i] + _T("/code"), wxEmptyString);
        if (name.IsEmpty() || code.IsEmpty())
            continue;
       
        code.Replace(_T("\\n"), _T("\n"));
        code.Replace(_T("\\r"), _T("\r"));
        code.Replace(_T("\\t"), _T("\t"));
        m_AutoCompleteMap[name] = code;
    }

    if (m_AutoCompleteMap.size() == 0)
    {
       
        m_AutoCompleteMap[_T("if")] = _T("if (|)\n\t;");
        m_AutoCompleteMap[_T("ifb")] = _T("if (|)\n{\n\t\n}");
        m_AutoCompleteMap[_T("ife")] = _T("if (|)\n{\n\t\n}\nelse\n{\n\t\n}");
        m_AutoCompleteMap[_T("ifei")] = _T("if (|)\n{\n\t\n}\nelse if ()\n{\n\t\n}\nelse\n{\n\t\n}");
        m_AutoCompleteMap[_T("guard")] = _T("#ifndef $(Guard token)\n#define $(Guard token)\n\n|\n\n#endif
        m_AutoCompleteMap[_T("while")] = _T("while (|)\n\t;");
        m_AutoCompleteMap[_T("whileb")] = _T("while (|)\n{\n\t\n}");
        m_AutoCompleteMap[_T("switch")] = _T("switch (|)\n{\n\tcase :\n\t\tbreak;\n\n\tdefault:\n\t\tbreak;\n}\n");
        m_AutoCompleteMap[_T("for")] = _T("for (|; ; )\n\t;");
        m_AutoCompleteMap[_T("forb")] = _T("for (|; ; )\n{\n\t\n}");
        m_AutoCompleteMap[_T("class")] = _T("class $(Class name)|\n{\n\tpublic:\n\t\t$(Class name)();\n\t\t~$(Class name)();\n\tprotected:\n\t\t\n\tprivate:\n\t\t\n};\n");
        m_AutoCompleteMap[_T("struct")] = _T("struct |\n{\n\t\n};\n");
    }

   
   
    const wxString timeAndDate[9][2] =
    {
        { _T("tday"), _T("$TDAY") },
        { _T("tdayu"), _T("$TDAY_UTC") },
        { _T("today"), _T("$TODAY") },
        { _T("todayu"), _T("$TODAY_UTC") },
        { _T("now"), _T("$NOW") },
        { _T("nowl"), _T("$NOW_L") },
        { _T("nowu"), _T("$NOW_UTC") },
        { _T("nowlu"), _T("$NOW_L_UTC") },
        { _T("wdu"), _T("$WEEKDAY_UTC") },
    };
    for (int i = 0; i < 9; ++i)
    {
        if (m_AutoCompleteMap.find(timeAndDate[i][0]) == m_AutoCompleteMap.end())
            m_AutoCompleteMap[timeAndDate[i][0]] = timeAndDate[i][1];
    }
}

void SEditorManager::SaveAutoComplete() {
    Manager::Get()->GetConfigManager(_T("editor"))->DeleteSubPath(_T("/auto_complete"));
    SAutoCompleteMap::iterator it;
    int count = 0;
    for (it = m_AutoCompleteMap.begin(); it != m_AutoCompleteMap.end(); ++it)
    {
        wxString code = it->second;
       
        code.Replace(_T("\n"), _T("\\n"));
        code.Replace(_T("\r"), _T("\\r"));
        code.Replace(_T("\t"), _T("\\t"));

        ++count;
        wxString key;
        key.Printf(_T("/auto_complete/entry%d/name"), count);
        Manager::Get()->GetConfigManager(_T("editor"))->Write(key, it->first);
        key.Printf(_T("/auto_complete/entry%d/code"), count);
        Manager::Get()->GetConfigManager(_T("editor"))->Write(key, code);
    }
}

int SEditorManager::GetEditorsCount() {
    return m_pNotebook->GetPageCount();
}

SEditorBase* SEditorManager::InternalGetEditorBase(int page) {
   
   
    if (page < (int)m_pNotebook->GetPageCount())
    {
        return static_cast<SEditorBase*>(m_pNotebook->GetPage(page));
    }
    return 0;
}

ScbEditor* SEditorManager::InternalGetBuiltinEditor(int page) {
    SEditorBase* eb = InternalGetEditorBase(page);
    if (eb && eb->IsBuiltinEditor())
        return (ScbEditor*)eb;
    return 0;
}

ScbEditor* SEditorManager::GetBuiltinEditor(SEditorBase* eb) {
    return eb && eb->IsBuiltinEditor() ? (ScbEditor*)eb : 0;
}

SEditorBase* SEditorManager::IsOpen(const wxString& filename) {
    wxString uFilename = UnixFilename(realpath(filename));
    for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
    {
        SEditorBase* eb = InternalGetEditorBase(i);
        if (!eb)
            continue;
        wxString fname = eb->GetFilename();

       
        if (fname.IsSameAs(uFilename, platform::windows == false) || fname.IsSameAs(g_EditorModified + uFilename, platform::windows == false))
            return eb;
    }

    return NULL;
}

SEditorBase* SEditorManager::GetEditor(int index) {
    return InternalGetEditorBase(index);
}

void SEditorManager::SetColourSet(SEditorColourSet* theme) {
    if (m_Theme)
        delete m_Theme;

   
   
    m_Theme = new SEditorColourSet(*theme);

    for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
    {
        ScbEditor* ed = InternalGetBuiltinEditor(i);
        if (ed)
            ed->SetColourSet(m_Theme);
    }
}

ScbEditor* SEditorManager::Open(const wxString& filename, int pos, ProjectFile* data) {
    LoaderBase* fileLdr = Manager::Get()->GetFileManager()->Load(filename);
    if (!fileLdr)
        return 0;

    return Open(fileLdr, filename, pos, data);
}

ScbEditor* SEditorManager::Open(LoaderBase* fileLdr, const wxString& filename, int pos,ProjectFile* data) {
    bool can_updateui = !GetActiveEditor() || !Manager::Get()->GetProjectManager()->IsLoading();
    wxFileName fn(realpath(filename));
    NormalizePath(fn, wxEmptyString);
    wxString fname = UnixFilename(fn.GetFullPath());
   
    if (!wxFileExists(fname))
        return NULL;
   

   
   
    s_CanShutdown = false;

    SEditorBase* eb = IsOpen(fname);
    ScbEditor* ed = 0;
    if (eb)
    {
        if (eb->IsBuiltinEditor())
            ed = (ScbEditor*)eb;
        else
            return 0;
    }

    if (!ed)
    {
        ed = new ScbEditor(m_pNotebook, fileLdr, fname, m_Theme);
        if (ed->IsOK())
            AddEditorBase(ed);
        else
        {
            ed->Destroy();
            ed = NULL;
        }
    }

    if(can_updateui)
    {
        if (ed)
        {
            SetActiveEditor(ed);
            ed->GetControl()->SetFocus();
        }
    }

   
    if (ed && !ed->GetProjectFile())
    {
       
       
        if(data)
        {
            Manager::Get()->GetLogManager()->DebugLog(_T("project data set for ") + data->file.GetFullPath());
        }
        else
        {
            ProjectsArray* projects = Manager::Get()->GetProjectManager()->GetProjects();
            for (unsigned int i = 0; i < projects->GetCount(); ++i)
            {
                cbProject* prj = projects->Item(i);
                ProjectFile* pf = prj->GetFileByFilename(ed->GetFilename(), false);
                if (pf)
                {
                    Manager::Get()->GetLogManager()->DebugLog(_T("found ") + pf->file.GetFullPath());
                    data = pf;
                    break;
                }
            }
        }
        if(data)
            ed->SetProjectFile(data,true);
    }

   
    s_CanShutdown = true;

    return ed;
}

SEditorBase* SEditorManager::GetActiveEditor() {
   
    if (m_pNotebook->GetPageCount() > 0)
    {
        return InternalGetEditorBase(m_pNotebook->GetSelection());
    }
    return 0;
}

void SEditorManager::ActivateNext() {
    m_pNotebook->AdvanceSelection(true);
}

void SEditorManager::ActivatePrevious() {
    m_pNotebook->AdvanceSelection(false);
}

void SEditorManager::SetActiveEditor(SEditorBase* ed) {
    if (!ed)
        return;
    if (ed->IsBuiltinEditor())
        static_cast<ScbEditor*>(ed)->GetControl()->SetFocus();
    int page = FindPageFromEditor(ed);
    if (page != -1)
    {
        m_pNotebook->SetSelection(page);
    }
}

ScbEditor* SEditorManager::New(const wxString& newFileName) {
//    wxString old_title = Manager::Get()->GetAppWindow()->GetTitle();
   
    if (!newFileName.IsEmpty() && !wxFileExists(newFileName) && wxDirExists(wxPathOnly(newFileName)))
    {
        wxFile f(newFileName, wxFile::write);
        if (!f.IsOpened())
            return 0;
    }
    ScbEditor* ed = new ScbEditor(m_pNotebook, newFileName);



   
    wxString key;
    key.Printf(_T("/default_code/set%d"), (int)FileTypeOf(ed->GetFilename()));
    wxString code = Manager::Get()->GetConfigManager(_T("editor"))->Read(key, wxEmptyString);
    ed->GetControl()->SetText(code);

    ed->SetColourSet(m_Theme);
    AddEditorBase(ed);

    ed->Show(true);
    SetActiveEditor(ed);
    CodeBlocksEvent evt(cbEVT_EDITOR_OPEN, -1, 0, (EditorBase*)ed);
   
   
    return ed;
}

void SEditorManager::AddCustomEditor(SEditorBase* eb) {
    AddEditorBase(eb);
}

void SEditorManager::RemoveCustomEditor(SEditorBase* eb) {
    RemoveEditorBase(eb, false);
}

void SEditorManager::AddEditorBase(SEditorBase* eb) {
    int page = FindPageFromEditor(eb);
    if (page == -1)
    {
       
        m_pNotebook->AddPage(eb, eb->GetTitle(), true);
    }
}

void SEditorManager::RemoveEditorBase(SEditorBase* eb, bool deleteObject) {
   
    int page = FindPageFromEditor(eb);
   if (page != -1 && !Manager::IsAppShuttingDown())
         m_pNotebook->RemovePage(page);

   
   
}

bool SEditorManager::UpdateSnippetFiles(cbProject* project) {
    for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
    {
        ScbEditor* ed = InternalGetBuiltinEditor(i);
        if (!ed)
            continue;
        ProjectFile* pf = ed->GetProjectFile();
        if (!pf)
            continue;
        if (pf->GetParentProject() != project)
            continue;
        pf->editorTopLine = ed->GetControl()->GetFirstVisibleLine();
        pf->editorPos = ed->GetControl()->GetCurrentPos();
        pf->editorTabPos = i + 1;
        pf->editorOpen = true;
    }
    return true;
}

bool SEditorManager::CloseAll(bool dontsave) {
   
    return CloseAllExcept(GetEditor(_("Start here")), dontsave);
}

bool SEditorManager::QueryCloseAll() {
    for (int i = m_pNotebook->GetPageCount() - 1; i >= 0; --i)
    {
        SEditorBase* eb = InternalGetEditorBase(i);
        if(eb && !QueryClose(eb))
            return false;
    }
    return true;
}

bool SEditorManager::CloseAllExcept(SEditorBase* editor,bool dontsave) {
    if(!dontsave)
    {
        for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
        {
            SEditorBase* eb = InternalGetEditorBase(i);
            if(eb && eb != editor && !QueryClose(eb))
                return false;
        }
    }

    m_pNotebook->Freeze();
    int count = m_pNotebook->GetPageCount();
    for (int i = m_pNotebook->GetPageCount() - 1; i >= 0; --i)
    {
        SEditorBase* eb = InternalGetEditorBase(i);
        if (eb && eb != editor && Close(eb, true))
            --count;
    }
    m_pNotebook->Thaw();
    return count == (editor ? 1 : 0);
}

bool SEditorManager::CloseActive(bool dontsave) {
    return Close(GetActiveEditor(),dontsave);
}

bool SEditorManager::QueryClose(SEditorBase *ed) {
    if(!ed)
        return true;
    if (ed->GetModified())
    {
       
        wxString msg;
        msg.Printf(_("File %s is modified...\nDo you want to save the changes?"), ed->GetFilename().c_str());
        switch (cbMessageBox(msg, _("Save file"), wxICON_QUESTION | wxYES_NO | wxCANCEL))
        {
        case wxID_YES:
            if (!ed->Save())
                return false;
            break;
        case wxID_NO:
            break;
        case wxID_CANCEL:
            return false;
        }
        ed->SetModified(false);
    }
    else
    {
        return ed->QueryClose();
    }
    return true;
}

int SEditorManager::FindPageFromEditor(SEditorBase* eb) {
    for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
    {
        if (m_pNotebook->GetPage(i) == eb)
            return i;
    }
    return -1;
}

bool SEditorManager::Close(const wxString& filename,bool dontsave) {
    return Close(IsOpen(filename),dontsave);
}

bool SEditorManager::Close(SEditorBase* editor,bool dontsave) {
    if (editor)
    {
        int idx = FindPageFromEditor(editor);
        if (idx != -1)
        {
            if(!dontsave)
                if(!QueryClose(editor))
                    return false;
            wxString filename = editor->GetFilename();
           
            m_pNotebook->DeletePage(idx);
        }
    }
    return true;
}

bool SEditorManager::Close(int index,bool dontsave) {
    SEditorBase* ed = InternalGetEditorBase(index);
    if (ed)
        return Close(ed,dontsave);
    return false;
}

bool SEditorManager::Save(const wxString& filename) {
   
    SEditorBase* ed = IsOpen(filename);
    if (ed)
    {
        wxString oldname = ed->GetFilename();
        if (!ed->Save())
            return false;
        return true;
    }
    return true;
}

bool SEditorManager::Save(int index) {
    SEditorBase* ed = InternalGetEditorBase(index);
    if (ed)
    {
        wxString oldname = ed->GetFilename();
        if (!ed->Save())
            return false;
        return true;
    }
    return false;
}

bool SEditorManager::SaveActive() {
    SEditorBase* ed = GetActiveEditor();
    if (ed)
    {
        wxString oldname = ed->GetFilename();
        if (!ed->Save())
            return false;
        return true;
    }
    return true;
}

bool SEditorManager::SaveAs(int index) {
    ScbEditor* ed = GetBuiltinEditor(GetEditor(index));
    if(!ed)
        return false;
    return ed->SaveAs();
}

bool SEditorManager::SaveActiveAs() {
    ScbEditor* ed = GetBuiltinEditor(GetActiveEditor());
    if (ed)
    {
        return ed->SaveAs();
    }
    return true;
}

bool SEditorManager::SaveAll() {
    for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
    {
        SEditorBase* ed = InternalGetEditorBase(i);
        if (ed && ed->GetModified() && !ed->Save())
        {
            wxString msg;
            msg.Printf(_("File %s could not be saved..."), ed->GetFilename().c_str());
            cbMessageBox(msg, _("Error saving file"), wxICON_ERROR);
        }
    }

    return true;
}

void SEditorManager::FilePrint(wxWindow* parent) {
    SPrintDialog dlg( parent, this);
    PlaceWindow(&dlg);
    if (dlg.ShowModal() == wxID_OK)
        Print(dlg.GetPrintScope(), dlg.GetPrintColourMode(), dlg.GetPrintLineNumbers());
}

void SEditorManager::Print(PrintScope ps, PrintColourMode pcm, bool line_numbers) {
    switch (ps)
    {
    case psAllOpenEditors:
        {
            for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
            {
                ScbEditor* ed = InternalGetBuiltinEditor(i);
                if (ed)
                    ed->Print(false, pcm, line_numbers);
            }
            break;
        }
    default:
        {
            ScbEditor* ed = GetBuiltinEditor(GetActiveEditor());
            if (ed)
                ed->Print(ps == psSelection, pcm, line_numbers);
            break;
        }
    }
}

void SEditorManager::CheckForExternallyModifiedFiles() {
    if(m_isCheckingForExternallyModifiedFiles)
        return;
    m_isCheckingForExternallyModifiedFiles = true;

    bool reloadAll = false;
    wxArrayString failedFiles;
    for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
    {
        ScbEditor* ed = InternalGetBuiltinEditor(i);
        bool b_modified = false;

       
        if (!ed || !ed->IsOK())
            continue;
       
        if (!wxFileExists(ed->GetFilename()))
        {
            if(ed->GetModified())
                continue;
            wxString msg;
            msg.Printf(_("%s has been deleted, or is no longer available.\n"
                         "Do you wish to keep the file open?\n"
                         "Yes to keep the file, No to close it."), ed->GetFilename().c_str());
            if (cbMessageBox(msg, _("File changed!"), wxICON_QUESTION | wxYES_NO) == wxID_YES)
                ed->SetModified(true);
            else
            {
                ed->Close();
                ProjectFile* pf = ed->GetProjectFile();
                if (pf)
                    pf->SetFileState(fvsMissing);
            }
            continue;
        }

        ProjectFile* pf = ed->GetProjectFile();
        wxFileName fname(ed->GetFilename());
        wxDateTime last = fname.GetModificationTime();

       
        if (ed->GetControl()->GetReadOnly() &&
                wxFile::Access(ed->GetFilename().c_str(), wxFile::write))
        {
            b_modified = false;
            ed->GetControl()->SetReadOnly(false);
            if (pf)
                pf->SetFileState(fvsNormal);
        }
       
        if (!ed->GetControl()->GetReadOnly() &&
                !wxFile::Access(ed->GetFilename().c_str(), wxFile::write))
        {
            b_modified = false;
            ed->GetControl()->SetReadOnly(true);
            if (pf)
                pf->SetFileState(fvsReadOnly);
        }
       
        if (last.IsLaterThan(ed->GetLastModificationTime()))
            b_modified = true;

        if (b_modified)
        {
           
            int ret = -1;
            if (!reloadAll)
            {
                wxString msg;
                msg.Printf(_("File %s is modified outside the IDE...\nDo you want to reload it (you will lose any unsaved work)?"),
                           ed->GetFilename().c_str());
                ConfirmReplaceDlg dlg(Manager::Get()->GetAppWindow(), false, msg);
                dlg.SetTitle(_("Reload file?"));
                PlaceWindow(&dlg);
                ret = dlg.ShowModal();
                reloadAll = ret == crAll;
            }
            if (reloadAll || ret == crYes)
            {
                if (!ed->Reload())
                    failedFiles.Add(ed->GetFilename());
            }
            else if (ret == crCancel)
                break;
            else if (ret == crNo)
                ed->Touch();
        }
    }

   
   
   
    SetActiveEditor(GetActiveEditor());

    if (failedFiles.GetCount())
    {
        wxString msg;
        msg.Printf(_("Could not reload all files:\n\n%s"), GetStringFromArray(failedFiles, _T("\n")).c_str());
        cbMessageBox(msg, _("Error"), wxICON_ERROR);
    }
    m_isCheckingForExternallyModifiedFiles = false;
}













































bool SEditorManager::IsHeaderSource(const wxFileName& testedFileName, const wxFileName& activeFileName, FileType ftActive) {
    if (testedFileName.GetName() == activeFileName.GetName())
    {
        FileType ftTested = FileTypeOf(testedFileName.GetFullName());
        if (    ((ftActive == ftHeader) && (ftTested == ftSource))
             || ((ftActive == ftSource) && (ftTested == ftHeader)) )
        {
            if (testedFileName.FileExists())
            {
                return true;
            }
        }
    }
    return false;
}

wxFileName SEditorManager::FindHeaderSource(const wxArrayString& candidateFilesArray, const wxFileName& activeFile, bool& isCandidate) {
    FileType ftActive = FileTypeOf(activeFile.GetFullName());

   
    bool extStartsWithCapital = wxIsupper(activeFile.GetExt()[0]);

    wxFileName candidateFile;
    for (unsigned i = 0; i < candidateFilesArray.GetCount(); ++i)
    {
        wxFileName currentCandidateFile(candidateFilesArray[i]);

        if (IsHeaderSource(currentCandidateFile, activeFile, ftActive))
        {
            bool isUpper = wxIsupper(currentCandidateFile.GetExt()[0]);
            if (isUpper == extStartsWithCapital)
            {
               
                isCandidate = false;
                return currentCandidateFile;
            }
            else
            {
               
               
                candidateFile = currentCandidateFile;
            }
        }
    }

    isCandidate = true;

   
    return candidateFile;
}

bool SEditorManager::SwapActiveHeaderSource() {
    ScbEditor* ed = GetBuiltinEditor(GetActiveEditor());
    if (!ed)
        return false;

    ProjectManager *pm = Manager::Get()->GetProjectManager();
    if (!pm)
        return false;

    FileType ft = FileTypeOf(ed->GetFilename());
    if (ft != ftHeader && ft != ftSource)
        return false;

    cbProject* project = 0;

   
   
   
   
    ProjectFile* opf = ed->GetProjectFile();
    if (opf)
        project = opf->GetParentProject();

   
    if (!project)
        project = pm->GetActiveProject();

    wxFileName theFile(ed->GetFilename());
    wxFileName candidateFile;
    bool isCandidate;
    wxArrayString fileArray;

   
   
    wxDir::GetAllFiles(theFile.GetPath(wxPATH_GET_VOLUME), &fileArray, theFile.GetName() + _T(".*"), wxDIR_FILES | wxDIR_HIDDEN);

   
    wxFileName currentCandidateFile = FindHeaderSource(fileArray, theFile, isCandidate);

    if (isCandidate)
    {
        candidateFile = currentCandidateFile;
    }
    else if (currentCandidateFile.IsOk())
    {
        ScbEditor* newEd = Open(currentCandidateFile.GetFullPath());
        if (newEd!=0L)
            return true;
    }

   

   
    fileArray.Clear();
    for (int i = 0; i < GetEditorsCount(); ++i)
    {
        ScbEditor* edit = GetBuiltinEditor(GetEditor(i));
        if (!edit)
            continue;

        ProjectFile* pf = edit->GetProjectFile();
        if (!pf)
            continue;

        fileArray.Add(pf->file.GetFullPath());
    }

   
    currentCandidateFile = FindHeaderSource(fileArray, theFile, isCandidate);

    if (!isCandidate && currentCandidateFile.IsOk())
    {
        ScbEditor* newEd = Open(currentCandidateFile.GetFullPath());
        if (newEd!=0L)
            return true;
    }

    if (project)
    {
       

       
        fileArray.Clear();
        for (FilesList::iterator it = project->GetFilesList().begin(); it != project->GetFilesList().end(); ++it)
        {
            ProjectFile* pf = *it;
            if (!pf)
                continue;

            fileArray.Add(pf->file.GetFullPath());
        }

       
        currentCandidateFile = FindHeaderSource(fileArray, theFile, isCandidate);

        if (isCandidate && !candidateFile.IsOk())
        {
            candidateFile = currentCandidateFile;
        }
        else if (currentCandidateFile.IsOk())
        {
            ScbEditor* newEd = Open(currentCandidateFile.GetFullPath());
            if (newEd!=0L)
                return true;
        }

       

       
        wxArrayString dirs = project->GetIncludeDirs();

       
        for (int i = 0; i < project->GetBuildTargetsCount(); ++i)
        {
            ProjectBuildTarget* target = project->GetBuildTarget(i);
            if (target)
            {
                for (unsigned int ti = 0; ti < target->GetIncludeDirs().GetCount(); ++ti)
                {
                   
                    wxString dir = target->GetIncludeDirs()[ti];
                    if (dirs.Index(dir) == wxNOT_FOUND)
                        dirs.Add(dir);
                }
            }
        }

       
        for (unsigned int i = 0; i < dirs.GetCount(); ++i)
        {
            wxString dir = dirs[i];
           
           

            wxFileName dname(dir);
            if (!dname.IsAbsolute())
            {
                dname.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE, project->GetBasePath());
   
            }

            fileArray.Clear();
           
            wxDir::GetAllFiles(dname.GetPath(), &fileArray, theFile.GetName() + _T(".*"), wxDIR_FILES | wxDIR_HIDDEN);
           
            currentCandidateFile = FindHeaderSource(fileArray, theFile, isCandidate);

            if (isCandidate)
            {
                candidateFile = currentCandidateFile;
            }
            else if (currentCandidateFile.IsOk())
            {
                ScbEditor* newEd = Open(currentCandidateFile.GetFullPath());
                if (newEd!=0L)
                    return true;
            }
        }
    }

   
   
    if (candidateFile.IsOk())
    {
        ScbEditor* newEd = Open(candidateFile.GetFullPath());
        if (newEd!=0L)
            return true;
    }

   
   
    if (cbMessageBox(_("The file seems not to exist. Do you want to create it?"),
                _("Error"), wxICON_QUESTION | wxYES_NO) == wxID_YES)
    {
        cbProject* project = Manager::Get()->GetProjectManager()->GetActiveProject();
        if (project)
            wxSetWorkingDirectory(project->GetBasePath());

       
        if      (ft == ftHeader)
            theFile.SetExt(FileFilters::CPP_EXT);
        else if (ft == ftSource)
            theFile.SetExt(FileFilters::H_EXT);
       
       

        ScbEditor* newEd = New(theFile.GetFullPath());
        if (project)
        {
            if (cbMessageBox(_("Do you want to add this new file in the active project?"),
                        _("Add file to project"),
                        wxYES_NO | wxICON_QUESTION) == wxID_YES)
            {
                wxArrayInt targets;
                if (Manager::Get()->GetProjectManager()->AddFileToProject(newEd->GetFilename(), project, targets) != 0)
                {
                    ProjectFile* pf = project->GetFileByFilename(newEd->GetFilename(), false);
                    newEd->SetProjectFile(pf);
                    Manager::Get()->GetProjectManager()->GetUI().RebuildTree();
                }
            }
        }

       
       
       
        CheckForExternallyModifiedFiles();
    }

    return false;
}

int SEditorManager::ShowFindDialog(bool replace, bool explicitly_find_in_files) {
    wxString phraseAtCursor;
    bool hasSelection = false;
    cbStyledTextCtrl* control = 0;

    ScbEditor* ed = GetBuiltinEditor(GetActiveEditor());
    if (ed)
    {
        control = ed->GetControl();

        hasSelection = control->GetSelectionStart() != control->GetSelectionEnd();
        int wordStart = control->WordStartPosition(control->GetCurrentPos(), true);
        int wordEnd = control->WordEndPosition(control->GetCurrentPos(), true);
        wxString wordAtCursor = control->GetTextRange(wordStart, wordEnd);
        phraseAtCursor = control->GetSelectedText();
       
        if (control->LineFromPosition(control->GetSelectionStart())
            == control->LineFromPosition(control->GetSelectionEnd()))
            hasSelection = false;

        if ( phraseAtCursor.IsEmpty())
            phraseAtCursor = wordAtCursor;

        int selstartline = control->LineFromPosition(control->GetSelectionStart());
        int selendline   = control->LineFromPosition(control->GetSelectionEnd());
       
        if ( selstartline != selendline )
            phraseAtCursor = wxEmptyString;

    }

    FindReplaceBase* dlg = new FindReplaceDlg(Manager::Get()->GetAppWindow(), phraseAtCursor, hasSelection,
                                              !replace, !ed, explicitly_find_in_files);

    PlaceWindow(dlg);
   
    wxPoint mousePosn = ::wxGetMousePosition();
    wxWindow* parentWin = wxFindWindowAtPoint(mousePosn);
    if (parentWin)
        GetConfig()->CenterChildOnParent( dlg, parentWin);
    else
        dlg->Move(mousePosn.x, mousePosn.y);

    if (dlg->ShowModal() == wxID_CANCEL)
    {
        dlg->Destroy();
        return -2;
    }

   
    if (dlg->GetFindString().empty())
    {
        dlg->Destroy();
        cbMessageBox(_("Can't look for an empty search criterion!"), _("Error"), wxOK | wxICON_EXCLAMATION, Manager::Get()->GetAppWindow());
        return -2;
    }

    if (!m_LastFindReplaceData)
        m_LastFindReplaceData = new cbFindReplaceData;

    m_LastFindReplaceData->start = 0;
    m_LastFindReplaceData->end = 0;
    m_LastFindReplaceData->findText = dlg->GetFindString();
    m_LastFindReplaceData->replaceText = dlg->GetReplaceString();

    m_LastFindReplaceData->findInFiles = dlg->IsFindInFiles();
    if(!m_LastFindReplaceData->findInFiles)
    {
       
        m_LastFindReplaceData->autoWrapSearch = dlg->GetAutoWrapSearch();

       
        if (!replace)
            m_LastFindReplaceData->findUsesSelectedText = dlg->GetFindUsesSelectedText();
    }
    m_LastFindReplaceData->delOldSearches = dlg->GetDeleteOldSearches();
    m_LastFindReplaceData->matchWord = dlg->GetMatchWord();
    m_LastFindReplaceData->startWord = dlg->GetStartWord();
    m_LastFindReplaceData->matchCase = dlg->GetMatchCase();
    m_LastFindReplaceData->regEx = dlg->GetRegEx();
    m_LastFindReplaceData->directionDown = dlg->GetDirection() == 1;
    m_LastFindReplaceData->originEntireScope = dlg->GetOrigin() == 1;
    m_LastFindReplaceData->scope = dlg->GetScope();
    m_LastFindReplaceData->searchPath = dlg->GetSearchPath();
    m_LastFindReplaceData->searchMask = dlg->GetSearchMask();
    m_LastFindReplaceData->recursiveSearch = dlg->GetRecursive();
    m_LastFindReplaceData->hiddenSearch = dlg->GetHidden();
    m_LastFindReplaceData->initialreplacing = false;
    m_LastFindReplaceData->NewSearch = true;
    if(control)
    {  
       
        m_LastFindReplaceData->SearchInSelectionStart = control->GetSelectionStart();
        m_LastFindReplaceData->SearchInSelectionEnd = control->GetSelectionEnd();
    }
    dlg->Destroy();

    int ReturnValue = 0;
    if (!replace)
    {
        if (m_LastFindReplaceData->findInFiles)
            ReturnValue = FindInFiles(m_LastFindReplaceData);
        else
            ReturnValue = Find(control, m_LastFindReplaceData);
    }
    else
    {
        m_LastFindReplaceData->initialreplacing = true;

        if (m_LastFindReplaceData->findInFiles)
            ReturnValue = ReplaceInFiles(m_LastFindReplaceData);
        else
            ReturnValue = Replace(control, m_LastFindReplaceData);
    }
    m_LastFindReplaceData->NewSearch = false;

   
    if(m_LastFindReplaceData->findInFiles)
    {
        m_LastFindReplaceData->findInFiles = false;
    }
    return ReturnValue;
}

void SEditorManager::CalculateFindReplaceStartEnd(cbStyledTextCtrl* control, cbFindReplaceData* data, bool replace) {
    if (!control || !data)
        return;

    if (!data->findInFiles)  
    {
        int ssta = control->GetSelectionStart();
        int send = control->GetSelectionEnd();
        int cpos = control->GetCurrentPos();
        int clen = control->GetLength();

       
       
       
       
       
       
       
        if(data->scope== 0 && data->NewSearch && (ssta != cpos || send != cpos))
        {
            ssta = cpos;
            send = cpos;
        }



        data->start = 0;
        data->end   = clen;

        if (!data->originEntireScope || !data->NewSearch)  
        {
            if (!data->directionDown)  
               
                data->start = (data->initialreplacing)? std::max(send, cpos) : std::min(ssta, cpos);
            else                     
               
                data->start = (data->initialreplacing)? std::min(ssta, cpos) : std::max(send, cpos);
        }
        else                           
        {
            if (!data->directionDown)  
                data->start = clen;
        }

        if (!data->directionDown)      
            data->end = 0;

       
        if (data->scope == 1 &&
            control->GetSelectionStart()==control->GetSelectionEnd())
                data->scope = 0;

        if (data->scope == 1)
        {
            if(data->NewSearch)
            {
                if (!data->directionDown)  
                {
                    data->start = std::max(ssta, send);
                    data->end   = std::min(ssta, send);
                }
                else
                {
                    data->start = std::min(ssta, send);
                    data->end   = std::max(ssta, send);
                }
            }
            else
            {  
               
                ssta = data->SearchInSelectionStart;
                send = data->SearchInSelectionEnd;
                if(cpos < ssta || cpos > send)
                {  
                    data->start = ssta;
                    data->end = send;
                }
                else
                {
                    data->start = cpos;
                    data->end = (data->directionDown)?send:ssta;
                }
            }
        }
    }
    else       
    {          
       
        data->start = ( replace ? 0 : control->GetCurrentPos() );
        data->end   = control->GetLength();
    }
}

int SEditorManager::Replace(cbStyledTextCtrl* control, cbFindReplaceData* data) {
    if (!control || !data)
        return -1;

    if (control->GetReadOnly())
    {
        cbMessageBox(_("This file is read-only.\nReplacing in a read-only file is not possible."),
                     _("Warning"), wxICON_EXCLAMATION);
        return -1;
    }

    bool AdvRegex=false;
    int replacecount=0;
    int foundcount=0;
    int flags = 0;
    CalculateFindReplaceStartEnd(control, data);

    if (data->matchWord)
        flags |= wxSCI_FIND_WHOLEWORD;
    if (data->startWord)
        flags |= wxSCI_FIND_WORDSTART;
    if (data->matchCase)
        flags |= wxSCI_FIND_MATCHCASE;
    if (data->regEx)
    {
        flags |= wxSCI_FIND_REGEXP;
        if (Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/use_posix_style_regexes"), false))
            flags |= wxSCI_FIND_POSIX;
        #ifdef wxHAS_REGEX_ADVANCED
        AdvRegex=Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/use_advanced_regexes"), false);
        #endif
    }

    wxRegEx re;
    #ifdef wxHAS_REGEX_ADVANCED
    if(AdvRegex)
    {
        if(data->matchCase)
            re.Compile(data->findText,wxRE_ADVANCED|wxRE_NEWLINE);
        else
            re.Compile(data->findText,wxRE_ADVANCED|wxRE_NEWLINE|wxRE_ICASE);
    }
    #endif

    control->BeginUndoAction();
    int pos = -1;
    bool replace = false;
    bool confirm = true;
    bool stop = false;
    wxPoint LastDlgPosition;
    bool HaveLastDlgPosition = false;
    bool wrapAround = false;
    int  data_start_initial = data->start;

    while (!stop)
    {
        int lengthFound = 0;
        if(!AdvRegex)
            pos = control->FindText(data->start, data->end, data->findText, flags, &lengthFound);
        else
        {
            wxString text=control->GetTextRange(data->start, data->end);
            if(re.Matches(text))
            {
                size_t start,len;
                re.GetMatch(&start,&len,0);
                pos=start+data->start;
                lengthFound=len;
                if(start==0&&len==0)
                {
                    text=text.Mid(1);
                    if(re.Matches(text))
                    {
                        size_t start,len;
                        re.GetMatch(&start,&len,0);
                        pos=start+data->start+1;
                        lengthFound=len;
                    } else
                        pos=-1;
                }
            } else
                pos=-1;
        }
        if (pos != -1 && data->start!=data->end)
        {
            control->GotoPos(pos);
            control->EnsureVisible(control->LineFromPosition(pos));
            control->SetSelectionVoid(pos, pos + lengthFound);
            data->start = pos;
            data->initialreplacing = false; 
        }
        else if (!wrapAround)
        {
            if ( (data->scope == 0) &&     
                    ((data->directionDown && data_start_initial != 0) ||
                     (!data->directionDown && data_start_initial != control->GetLength())))
            {
                wxString msg;
                if (data->directionDown)
                    msg = _("Text not found.\nSearch from the start of the document?");
                else
                    msg = _("Text not found.\nSearch from the end of the document?");

                bool auto_wrap_around = data->autoWrapSearch;
                if (auto_wrap_around)
                    wxBell();
                if (auto_wrap_around || cbMessageBox(msg, _("Result"), wxOK | wxCANCEL | wxICON_QUESTION) == wxID_OK)
                {
                    data->end = data_start_initial;
                    data->start = (data->directionDown)? 0 : control->GetLength();
                    wrapAround = true;
                    continue;
                }
                else
                    break; 
            }
            else
                break;
        }
        else
            break;

        foundcount++;

        if (confirm)
        {
            ConfirmReplaceDlg dlg(Manager::Get()->GetAppWindow());
           
           
           
           

           
           
           
           
           
            if ( HaveLastDlgPosition )
                dlg.Move(LastDlgPosition);
            else
                dlg.CalcPosition(control);

            int ans = dlg.ShowModal();
            LastDlgPosition = dlg.GetPosition();
            HaveLastDlgPosition = true;
            switch (ans)
            {
            case crYes:
                replace = true;
                break;
            case crNo:
                replace = false;
                break;
            case crAll:
                replace = true;
                confirm = false;
                break;
            case crCancel:
                stop = true;
                break;
            }
        }

        if (!stop)
        {
            if (replace)
            {
                int lengthReplace = data->replaceText.Length();
                replacecount++;
                if (data->regEx)
                {
                   
                    control->SetTargetStart(control->GetSelectionStart());
                    control->SetTargetEnd(control->GetSelectionEnd());
                    if(AdvRegex)
                    {
                        wxString text=control->GetSelectedText();
                        re.Replace(&text,data->replaceText,1);
                        lengthReplace=text.Len();
                        control->ReplaceSelection(text);
                    } else
                    {
                       
                        lengthReplace = control->ReplaceTargetRE(data->replaceText);
                    }
                   
                    control->SetTargetStart(0);
                    control->SetTargetEnd(0);
                }
                else
                    control->ReplaceSelection(data->replaceText);
                if (data->directionDown)
                {
                    data->start += lengthReplace;
                }
               
                int diff = lengthReplace - lengthFound;
                if (data->directionDown)
                {
                    data->end += diff;
                }
                else
                {
                    if(data->end < diff)
                    {
                       data->end = 0;
                    }
                    else
                    {
                       data->end -= diff;
                    }
                }
            }
            else
                if (data->directionDown)
                    data->start += lengthFound;
                else
                    data->start -= lengthFound;

        }
    }
    control->EndUndoAction();
    wxString msg;
    if (foundcount == 0)
        msg = _T("No matches found for \"") + data->findText + _T("\"");
    else if (replacecount == 0 && foundcount == 1)
        msg = _T("One match found but not replaced");
    else
        msg.Printf(_("Replaced %i of %i matches"), replacecount, foundcount);
    cbMessageBox(msg, _("Result"), wxICON_INFORMATION);
    control->SetSCIFocus(true);

    return pos;
}

int SEditorManager::ReplaceInFiles(cbFindReplaceData* data) {
    if (!data) return 0;
    if (data->findText.IsEmpty()) return 0;

   
    wxArrayString filesList;

    if (data->scope == 0)
    {
       
        cbProject* prj = Manager::Get()->GetProjectManager()->GetActiveProject();
        if (!prj)
            return 0;

        wxString fullpath = _T("");
        for (FilesList::iterator it = prj->GetFilesList().begin(); it != prj->GetFilesList().end(); ++it)
        {
            ProjectFile* pf = *it;
            if (pf)
            {
                fullpath = pf->file.GetFullPath();
                if (filesList.Index(fullpath) == -1)
                {
                    if(wxFileExists(fullpath)) 
                        filesList.Add(fullpath);
                }
            }
        }
    }
    else if (data->scope == 1)
    {
       
        for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
        {
            ScbEditor* ed = InternalGetBuiltinEditor(i);
            if (ed)
                filesList.Add(ed->GetFilename());
        }
    }
    else if (data->scope == 2)
    {
       
        const ProjectsArray* pProjects = Manager::Get()->GetProjectManager()->GetProjects();
        if(pProjects)
        {
            int count = pProjects->GetCount();
            for (int idxProject = 0; idxProject < count; ++idxProject)
            {
                cbProject* pProject = pProjects->Item(idxProject);
                if(pProject)
                {
                    wxString fullpath = _T("");
                    for (FilesList::iterator it = pProject->GetFilesList().begin(); it != pProject->GetFilesList().end(); ++it)
                    {
                        ProjectFile* pf = *it;
                        if (pf)
                        {
                            fullpath = pf->file.GetFullPath();
                            if (filesList.Index(fullpath) == -1)
                            {
                                if(wxFileExists(fullpath)) 
                                    filesList.Add(fullpath);
                            }
                        }
                    }
                }
            }
        }
    }

   
    int filesCount = filesList.GetCount();
    if (filesCount == 0)
    {
        cbMessageBox(_("No files to search in!"), _("Error"), wxICON_WARNING);
        return 0;
    }

    bool AdvRegex=false;
    int flags = 0;
    if (data->matchWord)
        flags |= wxSCI_FIND_WHOLEWORD;
    if (data->startWord)
        flags |= wxSCI_FIND_WORDSTART;
    if (data->matchCase)
        flags |= wxSCI_FIND_MATCHCASE;
    if (data->regEx)
    {
        flags |= wxSCI_FIND_REGEXP;
        if (Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/use_posix_style_regexes"), false))
            flags |= wxSCI_FIND_POSIX;
        #ifdef wxHAS_REGEX_ADVANCED
        AdvRegex=Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/use_advanced_regexes"), false);
        #endif
    }

    wxRegEx re;
    #ifdef wxHAS_REGEX_ADVANCED
    if(AdvRegex)
    {
        if(data->matchCase)
            re.Compile(data->findText,wxRE_ADVANCED|wxRE_NEWLINE);
        else
            re.Compile(data->findText,wxRE_ADVANCED|wxRE_NEWLINE|wxRE_ICASE);
    }
    #endif


    bool replace = false;
    bool confirm = true;
    bool stop = false;
    bool wholeFile = false;
    bool all = false;
    int pos = -1;

    wxPoint LastDlgPosition;
    bool HaveLastDlgPosition = false;

    wxProgressDialog* progress = 0;
    wxString fileContents;
    wxString enc_name = Manager::Get()->GetConfigManager(_T("editor"))->Read(_T("/default_encoding"), wxLocale::GetSystemEncodingName());
    wxFontEncoding def_encoding = wxFontMapper::GetEncodingFromName(enc_name);

   
    cbFindReplaceData dataCopy = *data;

    int read_only_files_skipped = 0;
    for (int i = 0; i<filesCount && !stop; ++i)
    {
        ScbEditor *ed = NULL;
        cbStyledTextCtrl *control = NULL;
        bool fileWasNotOpen = false;

        if (progress)
        {
            if (!progress->Update(i))
            {
                if (cbMessageBox(_("Are you sure you want to stop replacing in files?"), _("Confirmation"), wxICON_QUESTION | wxYES_NO) == wxID_YES)
                    break;
                else
                    progress->Resume();
            }
        }

       
        SEditorBase *eb = IsOpen(filesList[i]);
        if (eb)
        {
           
            fileWasNotOpen = false;

            ed = GetBuiltinEditor(eb);
            if (ed) control = ed->GetControl();
        }

       
        if (!control)
        {
            wxFile file(filesList[i]);
            if (!file.IsOpened())
                continue;
            fileContents = cbReadFileContents(file, def_encoding);
            if (fileContents.Find(data->findText) == -1)
                continue;

           
            fileWasNotOpen = true;

            ed = Open(filesList[i]);
            if (ed) control = ed->GetControl();
        }
       
        if (!control || !ed)
            continue;

        if (control->GetReadOnly())    
        {
            read_only_files_skipped++;
            continue;
        }

        SetActiveEditor(ed);
        control->BeginUndoAction();

        *data = dataCopy;
        CalculateFindReplaceStartEnd(control, data, true);

       
        wholeFile = false;
        if (!all) confirm = true;

       
        while(!stop || wholeFile)
        {
            int lengthFound = 0;
            if(!AdvRegex)
                pos = control->FindText(data->start, data->end, data->findText, flags, &lengthFound);
            else
            {
                wxString text=control->GetTextRange(data->start, data->end);
                if(re.Matches(text))
                {
                    size_t start,len;
                    re.GetMatch(&start,&len,0);
                    pos=start+data->start;
                    lengthFound=len;
                    if(start==0&&len==0)
                    {
                        text=text.Mid(1);
                        if(re.Matches(text))
                        {
                            size_t start2,len2;
                            re.GetMatch(&start2,&len2,0);
                            pos=start2+data->start+1;
                            lengthFound=len2;
                        } else
                            pos=-1;
                    }
                } else
                    pos=-1;
            }

            if (pos == -1 || data->start==data->end)
                break;

            if (confirm)
            {
                control->GotoPos(pos);
                control->EnsureVisible(control->LineFromPosition(pos));
            }
            control->SetSelectionVoid(pos, pos + lengthFound);
            data->start = pos;
            data->initialreplacing = false; 

            if (confirm)
            {
                ConfirmReplaceDlg dlg(Manager::Get()->GetAppWindow(), true);
               
               
               
               

               
               
               
               
               
                if ( HaveLastDlgPosition )
                    dlg.Move(LastDlgPosition);
                else
                    dlg.CalcPosition(control);

                int ans = dlg.ShowModal();
                LastDlgPosition = dlg.GetPosition();
                HaveLastDlgPosition = true;
                switch (ans)
                {
                    case crYes:
                        replace = true;
                        break;
                    case crNo:
                        replace = false;
                        break;
                    case crAllInFile:
                        confirm = false;
                        replace = true;
                        wholeFile = true;
                        break;
                    case crSkipFile:
                        confirm = false;
                        replace = false;
                        wholeFile = true;
                        break;
                    case crAll:
                        replace = true;
                        confirm = false;
                        all = true;
                       
                        progress = new wxProgressDialog(_("Replace in files"),
                                     _("Please wait while replacing in files..."),
                                     filesCount,
                                     Manager::Get()->GetAppWindow(),
                                     wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
                        PlaceWindow(progress);
                       
                        Manager::Get()->GetAppWindow()->Freeze();
                        break;
                    case crCancel:
                        stop = true;
                        break;
                }
            }
            if (!stop)
            {
                if (replace)
                {
                    int lengthReplace = data->replaceText.Length();
                    if (data->regEx)
                    {
                       
                        control->SetTargetStart(control->GetSelectionStart());
                        control->SetTargetEnd(control->GetSelectionEnd());
                        if(AdvRegex)
                        {
                            wxString text=control->GetSelectedText();
                            re.Replace(&text,data->replaceText,1);
                            lengthReplace=text.Len();
                            control->ReplaceSelection(text);
                        } else
                        {
                           
                            lengthReplace = control->ReplaceTargetRE(data->replaceText);
                        }
                       
                        control->SetTargetStart(0);
                        control->SetTargetEnd(0);
                    }
                    else
                        control->ReplaceSelection(data->replaceText);

                    data->start += lengthReplace;

                   
                   
                    int diff = lengthReplace - lengthFound;
                    if (data->directionDown)
                        data->end += diff;
                    else
                        data->end -= diff;
                }
                else
                {
                    if (data->directionDown)
                        data->start += lengthFound;
                    else
                        data->start -= lengthFound;
                }
            }// if
        }
        control->EndUndoAction();

       
       
        if (!ed->GetModified() && fileWasNotOpen)
            Close(ed, true);
    }
    if (read_only_files_skipped)
    {
        wxString msg;
        msg.Printf(_("Skipped %d read-only file(s)."), read_only_files_skipped);
        InfoWindow::Display(_("Warning"), msg);
    }

   
    if (progress)
        Manager::Get()->GetAppWindow()->Thaw();

    delete progress;
    return pos;
}

int SEditorManager::Find(cbStyledTextCtrl* control, cbFindReplaceData* data) {
    if (!control || !data)
        return -1;

    bool AdvRegex=false;
    int flags = 0;
    CalculateFindReplaceStartEnd(control, data);

    if (data->matchWord)
        flags |= wxSCI_FIND_WHOLEWORD;
    if (data->startWord)
        flags |= wxSCI_FIND_WORDSTART;
    if (data->matchCase)
        flags |= wxSCI_FIND_MATCHCASE;
    if (data->regEx)
    {
        flags |= wxSCI_FIND_REGEXP;
        if (Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/use_posix_style_regexes"), false))
            flags |= wxSCI_FIND_POSIX;
        #ifdef wxHAS_REGEX_ADVANCED
        AdvRegex=Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/use_advanced_regexes"), false);
        #endif
    }

    wxRegEx re;
    #ifdef wxHAS_REGEX_ADVANCED
    if(AdvRegex)
    {
        if(data->matchCase)
            re.Compile(data->findText,wxRE_ADVANCED|wxRE_NEWLINE);
        else
            re.Compile(data->findText,wxRE_ADVANCED|wxRE_NEWLINE|wxRE_ICASE);
    }
    #endif

    int pos = -1;
   
    bool wrapAround = false;
    int StartPos = 0;
    int EndPos = control->GetLength();
    if(data->scope == 1)
    {
        StartPos = data->SearchInSelectionStart;
        EndPos = data->SearchInSelectionEnd;
    }
    while (true)
    {
        int lengthFound = 0;
        if(!AdvRegex)
            pos = control->FindText(data->start, data->end, data->findText, flags, &lengthFound);
        else
        {
            wxString text=control->GetTextRange(data->start, data->end);
            if(re.Matches(text))
            {
                size_t start,len;
                re.GetMatch(&start,&len,0);
                pos=start+data->start;
                lengthFound=len;
                if(start==0&&len==0)
                {
                    text=text.Mid(1);
                    if(re.Matches(text))
                    {
                        size_t start2,len2;
                        re.GetMatch(&start2,&len2,0);
                        pos=start2+data->start+1;
                        lengthFound=len2;
                    } else
                        pos=-1;
                }
            } else
                pos=-1;
        }
        if (pos != -1 && data->start!=data->end)
        {
            int line = control->LineFromPosition(pos);
            int onScreen = control->LinesOnScreen() >> 1;
            int l1 = line - onScreen;
            int l2 = line + onScreen;
            for(int l=l1; l<=l2;l+=2)      
                control->EnsureVisible(l);
            control->GotoLine(l1);         
            control->GotoLine(l2);
            control->GotoLine(line);
            control->SetSelectionVoid(pos, pos + lengthFound);
           
            data->start = pos;
            break;
        }
        else if (!wrapAround && !data->findInFiles)
        {
            if (     (data->directionDown && data->start != StartPos) ||
                     (!data->directionDown && data->start != EndPos)     )
            {
                wxString msg;
                if(!data->scope == 1)
                {
                    if (data->directionDown)
                        msg = _("Text not found.\nSearch from the start of the document?");
                    else
                        msg = _("Text not found.\nSearch from the end of the document?");
                }
                else
                {
                    if (data->directionDown)
                        msg = _("Text not found.\nSearch from the start of the selection?");
                    else
                        msg = _("Text not found.\nSearch from the end of the selection?");
                }

                bool auto_wrap_around = data->autoWrapSearch;
                if (auto_wrap_around)
                    wxBell();
                if (auto_wrap_around || cbMessageBox(msg, _("Result"), wxOK | wxCANCEL | wxICON_QUESTION) == wxID_OK)
                {
                    wrapAround = true;
                    if(!data->scope == 1)
                    {
                        if (data->directionDown)
                        {
                            data->start = 0;
                            data->end = control->GetLength();
                        }
                        else
                        {
                            data->start = control->GetLength();
                            data->end = 0;
                        }
                    }
                    else
                    {
                        if (data->directionDown)
                        {
                            data->start = data->SearchInSelectionStart;
                            data->end = data->SearchInSelectionEnd;
                        }
                        else
                        {
                            data->start = data->SearchInSelectionEnd;
                            data->end = data->SearchInSelectionStart;
                        }
                    }
                }
                else
                    break;
            }
            else
            {
                wxString msg;
                msg.Printf(_("Not found: %s"), data->findText.c_str());
                cbMessageBox(msg, _("Result"), wxICON_INFORMATION);
                control->SetSCIFocus(true);
                break;
            }
        }
        else if (wrapAround)
        {
            wxString msg;
            msg.Printf(_("Not found: %s"), data->findText.c_str());
            cbMessageBox(msg, _("Result"), wxICON_INFORMATION);
            break;
        }
        else
            break;
    }
    return pos;
}

int SEditorManager::FindInFiles(cbFindReplaceData* data) {
   
    return 0;


    if (!data || data->findText.IsEmpty())
        return 0;

   
    if ( data->delOldSearches )
    {
        m_pSearchLog->Clear();
    }
    int oldcount = m_pSearchLog->GetItemsCount();

   
    wxArrayString filesList;

    if (data->scope == 0)
    {
       
        cbProject* prj = Manager::Get()->GetProjectManager()->GetActiveProject();
        if (!prj)
        {
            cbMessageBox(_("No project to search in!"), _("Error"), wxICON_WARNING);
            return 0;
        }

        wxString fullpath = _T("");
        for (FilesList::iterator it = prj->GetFilesList().begin(); it != prj->GetFilesList().end(); ++it)
        {
            ProjectFile* pf = *it;
            if (pf)
            {
                fullpath = pf->file.GetFullPath();
                if (filesList.Index(fullpath) == -1)
                {
                    if(wxFileExists(fullpath)) 
                        filesList.Add(fullpath);
                }
            }
        }
    }
    else if (data->scope == 1)
    {
       
        for (size_t i = 0; i < m_pNotebook->GetPageCount(); ++i)
        {
            ScbEditor* ed = InternalGetBuiltinEditor(i);
            if (ed)
                filesList.Add(ed->GetFilename());
        }
    }
    else if (data->scope == 2)
    {
       
        int flags = wxDIR_FILES |
                    (data->recursiveSearch ? wxDIR_DIRS : 0) |
                    (data->hiddenSearch ? wxDIR_HIDDEN : 0);
        wxArrayString masks = GetArrayFromString(data->searchMask);
        if (!masks.GetCount())
            masks.Add(_T("*"));
        unsigned int count = masks.GetCount();

        for (unsigned int i = 0; i < count; ++i)
        {
           
            wxDir::GetAllFiles(data->searchPath, &filesList, masks[i], flags);
        }
    }
    else if (data->scope == 3)
    {
       
        const ProjectsArray* pProjects = Manager::Get()->GetProjectManager()->GetProjects();
        int count = 0;
        if(pProjects)
            count = pProjects->GetCount();
        if(!count)
        {
            cbMessageBox(_("No workspace to search in!"), _("Error"), wxICON_WARNING);
            return 0;
        }
        for (int idxProject = 0; idxProject < count; ++idxProject)
        {
            cbProject* pProject = pProjects->Item(idxProject);
            if(pProject)
            {
                wxString fullpath = _T("");
                for (FilesList::iterator it = pProject->GetFilesList().begin(); it != pProject->GetFilesList().end(); ++it)
                {
                    ProjectFile* pf = *it;
                    if (pf)
                    {
                        fullpath = pf->file.GetFullPath();
                        if (filesList.Index(fullpath) == -1)
                        {
                            if(wxFileExists(fullpath)) 
                                filesList.Add(fullpath);
                        }
                    }
                }
            }
        }
    }

   
    if (filesList.GetCount() == 0)
    {
        cbMessageBox(_("No files to search in!"), _("Error"), wxICON_WARNING);
        return 0;
    }

   
   
    cbStyledTextCtrl* control = new cbStyledTextCtrl(m_pNotebook, -1, wxDefaultPosition, wxSize(0, 0));
    control->Show(false);

   
    wxProgressDialog* progress = new wxProgressDialog(_("Find in files"),
                                 _("Please wait while searching inside the files..."),
                                 filesList.GetCount(),
                                 Manager::Get()->GetAppWindow(),
                                 wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);

    PlaceWindow(progress);

   
    cbFindReplaceData localData = *data;

    if ( !data->delOldSearches )
    {
        LogSearch(_T("=========="), -1, _T("=== \"") + data->findText + _T("\" ==="));
        oldcount++;
    }

    int lastline = -1;
    int count = 0;
    for (size_t i = 0; i < filesList.GetCount(); ++i)
    {
       
        if (!progress->Update(i))
            break;

       
        *data = localData;

       
        ScbEditor* ed = IsBuiltinOpen(filesList[i]);
        if (ed)
            control->SetText(ed->GetControl()->GetText());
        else
        {
            EncodingDetector detector(filesList[i]);
            if (!detector.IsOK())
            {
                continue;
            }
            control->SetText(detector.GetWxStr());
        }

       
        if (Find(control, data) == -1)
        {
            lastline = -1;
            continue;
        }

        int line = control->LineFromPosition(control->GetSelectionStart());
        lastline = line;

       
        wxString filename = filesList[i];
        if (filename.StartsWith(data->searchPath))
        {
            wxFileName fname(filename);
            fname.MakeRelativeTo(data->searchPath);
            filename = fname.GetFullPath();
        }

       
        LogSearch(filename, line + 1, control->GetLine(line));
        ++count;

       
        while (FindNext(true, control, data) != -1)
        {
           
            line = control->LineFromPosition(control->GetSelectionStart());
            if(line == lastline) 
                continue;

            lastline = line;
            LogSearch(filename, line + 1, control->GetLine(line));
            ++count;
        }
    }
    delete control;
    delete progress;

    if (count > 0)
    {
        static_cast<cbSearchResultsLog*>(m_pSearchLog)->SetBasePath(data->searchPath);
        if (Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_show_search"), true))
        {
            CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, m_pSearchLog);
            CodeBlocksLogEvent evtShow(cbEVT_SHOW_LOG_MANAGER);

            Manager::Get()->ProcessEvent(evtSwitch);
            Manager::Get()->ProcessEvent(evtShow);
        }
        static_cast<cbSearchResultsLog*>(m_pSearchLog)->FocusEntry(oldcount);
    }
    else
    {
        wxString msg;
        if ( data->delOldSearches )
        {
            msg.Printf(_("Not found: %s"), data->findText.c_str());
            cbMessageBox(msg, _("Result"), wxICON_INFORMATION);
           
            ScbEditor* ed = GetBuiltinActiveEditor();
            if (ed)
                ed->GetControl()->SetSCIFocus(true);
        }
        else
        {
            msg.Printf(_("not found in %d files"), filesList.GetCount());
            LogSearch(_T(""), -1, msg );
            static_cast<cbSearchResultsLog*>(m_pSearchLog)->FocusEntry(oldcount);
        }
    }

    return count;
}

int SEditorManager::FindNext(bool goingDown, cbStyledTextCtrl* control, cbFindReplaceData* data) {
    if (!control)
    {
        ScbEditor* ed = GetBuiltinEditor(GetActiveEditor());
        if (ed)
            control = ed->GetControl();
    }
    if (!control)
        return -1;

    if (!data)
    {
        data = m_LastFindReplaceData;
       
        if(data) data->findInFiles = false;
    }

    if (!data)
        return ShowFindDialog(false, false);

    if(!data->findInFiles)
    {
        wxString phraseAtCursor = control->GetSelectedText();

        if ( not data->findUsesSelectedText )
        {  
           
            if (!phraseAtCursor.IsEmpty() && data->findText.IsEmpty())
                data->findText = phraseAtCursor;
        }
        else
        {  
           
            if (!phraseAtCursor.IsEmpty())
            {
                data->findText = phraseAtCursor;
                data->originEntireScope = false; 
                data->scope = 0;
            }
        }
    }

    data->directionDown = goingDown;
    return Find(control, data);
}

void SEditorManager::OnGenericContextMenuHandler(wxCommandEvent& event) {
    SEditorBase* eb = GetActiveEditor();
    ScbEditor* ed = GetBuiltinEditor(eb);
    int id = event.GetId();

    if (id == idNBTabSplitHorz && ed)
        ed->Split(ScbEditor::stHorizontal);
    else if (id == idNBTabSplitVert && ed)
        ed->Split(ScbEditor::stVertical);
    else if (id == idNBTabUnsplit && ed)
        ed->Unsplit();
}

void SEditorManager::OnPageChanged(wxAuiNotebookEvent& event) {
    SEditorBase* eb = static_cast<SEditorBase*>(m_pNotebook->GetPage(event.GetSelection()));
   
    CodeBlocksEvent evt(cbEVT_EDITOR_ACTIVATED, -1, 0, (EditorBase*)eb);
   
   

   
    m_pData->m_SetFocusFlag = true;

    event.Skip();
}

void SEditorManager::OnPageChanging(wxAuiNotebookEvent& event) {
    SEditorBase* eb = static_cast<SEditorBase*>(m_pNotebook->GetPage(event.GetOldSelection()));
   
    CodeBlocksEvent evt(cbEVT_EDITOR_DEACTIVATED, -1, 0, (EditorBase*)eb);
   
   

    event.Skip();
}

void SEditorManager::OnPageClose(wxAuiNotebookEvent& event) {
    SEditorBase* eb = static_cast<SEditorBase*>(m_pNotebook->GetPage(event.GetSelection()));
   
    if (!QueryClose(eb))
        event.Veto();
    event.Skip();
}

void SEditorManager::OnTabRightUp(wxAuiNotebookEvent& event) {
    if (event.GetSelection() == -1)
        return;
    wxMenu* pop = new wxMenu;
    pop->Append(idNBTabClose, _("Close"));
    if (GetEditorsCount() > 1)
    {
        pop->Append(idNBTabCloseAll, _("Close all"));
        pop->Append(idNBTabCloseAllOthers, _("Close all others"));
    }
    pop->AppendSeparator();
    pop->Append(idNBTabSave, _("Save"));
    pop->Append(idNBTabSaveAll, _("Save all"));
    pop->AppendSeparator();
    pop->Append(idNBSwapHeaderSource, _("Swap header/source"));
    pop->AppendSeparator();
    pop->Append(idNBTabTop, _("Tabs at top"));
    pop->Append(idNBTabBottom, _("Tabs at bottom"));

    ScbEditor* ed = GetBuiltinEditor(event.GetSelection());
    if (ed)
    {
        pop->AppendSeparator();
        pop->Append(idNBProperties, _("Properties..."));

        wxMenu* splitMenu = new wxMenu;
        splitMenu->Append(idNBTabSplitHorz, _("Horizontally"));
        splitMenu->Append(idNBTabSplitVert, _("Vertically"));
        splitMenu->AppendSeparator();
        splitMenu->Append(idNBTabUnsplit, _("Unsplit"));
        splitMenu->Enable(idNBTabSplitHorz, ed->GetSplitType() != ScbEditor::stHorizontal);
        splitMenu->Enable(idNBTabSplitVert, ed->GetSplitType() != ScbEditor::stVertical);
        splitMenu->Enable(idNBTabUnsplit, ed->GetSplitType() != ScbEditor::stNoSplit);

        pop->AppendSeparator();
        pop->Append(-1, _("Split view"), splitMenu);
    }

    bool any_modified = false;

    for(int i = 0; i < GetEditorsCount(); ++i)
    {
        SEditorBase* ed2 = GetEditor(i);
        if (ed2 && ed2->GetModified())
        {
            any_modified = true;
            break;
        }
    }

    pop->Enable(idNBTabSave, GetEditor(event.GetSelection())->GetModified());
    pop->Enable(idNBTabSaveAll, any_modified );

    m_pNotebook->PopupMenu(pop);
    delete pop;
}

void SEditorManager::OnClose(cb_unused wxCommandEvent& event) {
   
    Close(GetActiveEditor());
}

void SEditorManager::OnCloseAll(cb_unused wxCommandEvent& event) {
   
    CloseAll();
}

void SEditorManager::OnCloseAllOthers(cb_unused wxCommandEvent& event) {
   
    CloseAllExcept(GetActiveEditor());
}

void SEditorManager::OnSave(cb_unused wxCommandEvent& event) {
   
    Save(m_pNotebook->GetSelection());
}

void SEditorManager::OnSaveAll(cb_unused wxCommandEvent& event) {
   
    SaveAll();
}

void SEditorManager::OnSwapHeaderSource(cb_unused wxCommandEvent& event) {
   
    SwapActiveHeaderSource();
}

void SEditorManager::OnTabPosition(wxCommandEvent& event) {
    long style = m_pNotebook->GetWindowStyleFlag();
    style &= ~wxAUI_NB_BOTTOM;

    if (event.GetId() == idNBTabBottom)
        style |= wxAUI_NB_BOTTOM;
    m_pNotebook->SetWindowStyleFlag(style);
   
    Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/environment/editor_tabs_bottom"), (bool)(style & wxAUI_NB_BOTTOM));
}

void SEditorManager::OnProperties(cb_unused wxCommandEvent& event) {
    ScbEditor* ed = GetBuiltinActiveEditor();
    ProjectFile* pf = 0;
    if (ed)
        pf = ed->GetProjectFile();
    if (pf)
        pf->ShowOptions(Manager::Get()->GetAppWindow());
    else
    {
       
       
        EditProperties dlg(m_pParent, GetBuiltinActiveEditor());
       
    }
}

void SEditorManager::OnAppDoneStartup(wxCommandEvent& event) {
    event.Skip();
}

void SEditorManager::OnAppStartShutdown(wxCommandEvent& event) {
    event.Skip();
}

void SEditorManager::OnCheckForModifiedFiles(cb_unused wxCommandEvent& event) {
    CheckForExternallyModifiedFiles();
}

void SEditorManager::HideNotebook() {
   
   
   
   
   
   
}

void SEditorManager::ShowNotebook() {
   
   
   
   
   
   
   
}

void SEditorManager::OnUpdateUI(wxUpdateUIEvent& event) {
    
    if (!Manager::Get()->IsAppShuttingDown() && m_pData->m_SetFocusFlag)
    {
        ScbEditor* ed = GetBuiltinActiveEditor();
        if (ed)
            ed->GetControl()->SetFocus();
        m_pData->m_SetFocusFlag = false;
    }

   
   
    event.Skip();
}

void SEditorManager::SetZoom(int zoom) {
    m_zoom = zoom;
}

int SEditorManager::GetZoom() const {
    return m_zoom;
}

int SEditorManager::GetManagerID() {
    return ID_NBSEditorManager;
}

int SEditorManager::GetLongestLinePixelWidth(int top_line, int bottom_line) 
{
    int ste_ctrlCharLengths[32] = { 3, 3, 3, 3, 3, 3, 3, 3,
                                       2, 2, 2, 2, 2, 2, 2, 2,
                                       3, 3, 3, 3, 3, 3, 3, 3,
                                       3, 2, 3, 3, 2, 2, 2, 2 };

    cbStyledTextCtrl* ed = GetBuiltinActiveEditor()->GetControl();
    if (not ed) return 0;

    int longest_len   = 0;
    int first_line    = (top_line < 0) ? ed->GetFirstVisibleLine() : top_line;
    int line_count    = ed->GetLineCount();
    int lines_visible = ed->LinesOnScreen();
    int last_line     = bottom_line < 0 ? wxMin(line_count, first_line + lines_visible) : bottom_line;
    int tab_width     = ed->GetTabWidth();
    int ctrl_char_symbol = ed->GetControlCharSymbol();

    if (last_line < first_line)
    {
        int tmp = first_line; first_line = last_line; last_line = tmp;
    }

   
   
    for (int n = first_line; n <= last_line; n++)
    {
        int len = ed->LineLength(n);

        int tabs = 0;
        if ((tab_width > 1) && (len*tab_width > longest_len))
        {
           
            wxCharBuffer buf = ed->GetLineRaw(n);
            const char* c = buf.data();
            for (int i = 0; i < len; i++, c++)
            {
                if (*c == '\t')
                    tabs += tab_width - ((i + tabs) % tab_width);
                else if ((ctrl_char_symbol >= 32) && (size_t(*c) < 32))
                {
                   
                    tabs += ste_ctrlCharLengths[size_t(*c)] - 1;
                }
            }

           
        }
        len += tabs + 3;
        if (longest_len < len) longest_len = len;
    }
   
   
    return ed->TextWidth(0, wxString(longest_len, wxT('D')));
}

